using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using eee.Sheffield.PZ.Math;

namespace eee.Sheffield.PZ.Imaging.ImageFilter
{
    public class TaskMCMCGVFThinning:ImageFilter
    {
        #region Fields
        private Bitmap _srcImage;
        private Bitmap _thinningImage;
        private MCMCGVFThinning _MCMCGVFThinning;
        private string _freeEndListFileName = "";
        private string _junctionListFileName = "";
        private string _GVFUFileName = "";
        private string _GVFVFileName = "";
        private string _GVFVectorMagnitudeFileName = "";
        #endregion

        #region Properties
        public MCMCGVFThinning MCMCGVFThinningFilter { get { return _MCMCGVFThinning; } }
        #endregion

        #region Constructor
        public TaskMCMCGVFThinning (Bitmap srcImage, Bitmap thinningImage)
        {
            _srcImage = srcImage;
            _thinningImage = thinningImage;

            _flag = "[Image -> Test -> Task MCMC GVF Thinning]";
        }

        public TaskMCMCGVFThinning(Bitmap srcImage, Bitmap thinningImage, string freeEndListFileName, string junctionListFileName)
        {
            _srcImage = srcImage;
            _thinningImage = thinningImage;
            _freeEndListFileName = freeEndListFileName;
            _junctionListFileName = junctionListFileName;

            _flag = "[Image -> Test -> Task MCMC GVF Thinning]";
        }

        public TaskMCMCGVFThinning(Bitmap srcImage, Bitmap thinningImage, string freeEndListFileName, string junctionListFileName,
            string GVFUFileName, string GVFVFileName, string GVFVectorMagnitudeFileName)
        {
            _srcImage = srcImage;
            _thinningImage = thinningImage;
            _freeEndListFileName = freeEndListFileName;
            _junctionListFileName = junctionListFileName;
            _GVFVFileName = GVFVFileName;
            _GVFUFileName = GVFUFileName;
            _GVFVectorMagnitudeFileName = GVFVectorMagnitudeFileName;
            _flag = "[Image -> Test -> Task MCMC GVF Thinning]";
        }

        #endregion

        #region overide methods
        protected override PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix, out string logText)
        {
            #region prepare source
            // threshold          
            SISThreshold thresholdFilter = new SISThreshold();
            thresholdFilter.Apply(_srcImage);            
            int intensityThreshold = thresholdFilter.Threshold;
            Console.WriteLine("threshold done");

            // GVF
            double sigma = 1.0;
            double mu = 0.2;
            GradientVectorFlow gvfFilter = new GradientVectorFlow(sigma, mu);
            if (_GVFVFileName != "")
            {
                gvfFilter.ReadFileV(_GVFVFileName);
                gvfFilter.ReadFileU(_GVFUFileName);
                gvfFilter.ReadFileVectorMagnitude(_GVFVectorMagnitudeFileName);
            }
            else
            {
                gvfFilter.Apply(_srcImage);
            }
            Console.WriteLine("GVF done");

            // get line segment configuration
            TripleJunctionDetector junctionDetector = new TripleJunctionDetector();
            if (_junctionListFileName == "")
                junctionDetector.ApplyGraylevelImageFilter(_thinningImage);
            else
                junctionDetector.ReadFile(_junctionListFileName);
            Console.WriteLine("junction detection done");

            FreeEndDetector freeEndDetector = new FreeEndDetector();
            if (_freeEndListFileName == "")
                freeEndDetector.ApplyGraylevelImageFilter(_thinningImage);
            else
                freeEndDetector.ReadFile(_freeEndListFileName);
            Console.WriteLine("free end detection done");

            LineSegmentSplitter splitter = new LineSegmentSplitter(freeEndDetector.FreeEndList, junctionDetector.TripleJunctionList);
            splitter.ApplyGraylevelImageFilter(_thinningImage);
            Console.WriteLine("line split done");
            #endregion

            // configurate
            LineSegmentConfiguration c = new LineSegmentConfiguration(splitter.LineSegmentList);
            c.InitLineSegmentIndex();
            c.AssignDataTerm(_srcImage, gvfFilter.U, gvfFilter.V, gvfFilter.VectorMagnitude);

            // parameters
            c.W1 = -0.5;       // # of line segments
            c.W2 = 1;       // # of free line segments
            c.W3 = 1;       // # of free ends
            c.WC = 1;     // connection
            c.WL = 0.5;     // length
            c.WG = 0.6;     // Gs value
            c.WI = 0.6;     // Is value

            c.Gt = 0.70;
            c.It = thresholdFilter.Threshold;
            c.KI = 1;

            // prepare MCMC GVF sampler
            int total = 20000;
            int burnin = 1000;
            int space = 100;
            _MCMCGVFThinning = new MCMCGVFThinning(_srcImage, gvfFilter.U, gvfFilter.V, gvfFilter.VectorMagnitude, c, total, burnin, space);
            
            // do MCMC, dstImage is the line segments with high hit probability            
            PZMath_matrix dstMatrix = _MCMCGVFThinning.ApplyDoubleGraylevelImageFilter(new PZMath_matrix(1, 1));
            logText = "success";
            return dstMatrix;
        }

        protected override PZMath_matrix[] ApplyDoubleColourImageFilter(PZMath_matrix[] srcMatrixArray, out string logText)
        {
            throw new Exception("The method or operation is not implemented.");
        }
        #endregion
    }
}

